home *** CD-ROM | disk | FTP | other *** search
- #import "MultApp.h"
- #import "MultDoc.h"
- #import "Help.h"
- #import "PrefDelegate.h"
- #import "PageMargin.h"
- #import <appkit/appkit.h>
-
- @implementation MultApp:Object
-
- /* Canon Information Systems is not responsible for anything anyone does with this */
- /* code, nor are they responsible for the correctness of this code. Basically, this */
- /* has very little to do with the company I work for, and you can't blame them. */
-
- /* This file is best read in a window as wide as this comment, and with tab settings */
- /* of 4 spaces and indent setting of 4 spaces (at least, that's what I use). */
-
- /* You are welcome to do as you would with this file under the following conditions. */
- /* First, I accept no blame for anything that goes wrong no matter how you use it, */
- /* no matter how catastrophic, not even if it stems from a bug in my code. */
- /* Second, please keep my notices on it when/if you distribute it. */
- /* Third, if you discover any bugs or have any comments, PLEASE TELL ME! Code won't */
- /* get better without people picking it apart and giving the writer feedback. */
- /* Fourth, if you modify it, please keep a notice that your version is based on mine */
- /* in the source files (and keep the notice that mine is based on four other pieces */
- /* of code :<). Thanks, and have fun. - Subrata Sircar, ssircar@canon.com */
-
- /* This class is intended as an Application Delegate. As such it */
- /* is supposed to provide the document-management functionality */
- /* that a multiple-document, drag-and-drop application should be */
- /* able to do. This includes keeping track of the current thing, */
- /* managing the shared panels, updating the defaults and menus, */
- /* and controlling communication with the Workspace Manager. */
-
- /* The paradigm used is that the application delegate relays new messages */
- /* to the factory Document class, and every other doc message goes to */
- /* the first responder. The delegate opens nib sections containing */
- /* the info and preferences panel (the prefs panel should have a delegate */
- /* to update it) and lets the helpObject worry about itself. Otherwise */
- /* it acts on delegate messages. */
-
- /* Source code stolen from Draw, Acceptor, and WhatsUpDoc. Thanks! */
- /* Source code also taken from Ernest Prabhakar's BasicApp example, which */
- /* includes more methods than mine does (for things like services, etc.) */
- /* His examples are well worth checking out, especially if you need more */
- /* functionality than this class can provide. */
- /* - Subrata Sircar ssircar@canon.com Canon Information Systems */
-
- /* Version 0.9b Apr-19-92 First Public Release */
- /* Version 0.95b Jun-10-92 Minor File path fixes */
- /* Version 1.0b Aug-10-92 Minor Bug Fixes */
-
- /* Preprocessor macros */
-
- #define DocClass [[[self class] docClass] class]
- #define DocExtension [DocClass extension]
- #define theVersion ((float)([[self class] version])/100.0)
- #define marginDefault "36.0"
-
- /* Factory (Class) Variables */
- /* These are declared as static internal because I felt that all members */
- /* of this class would use the same values for these variables. Subclasses */
- /* can only manipulate these variables through the provided class methods. */
- /* BE VERY CAREFUL about overriding methods which depends on the class */
- /* variables without calling the super method - it might cause problems. */
-
- static id docClass; /* Class of Document to use */
-
- static const char *theAppName; /* Cache the appName for later use */
- static const char *noValue; /* Cache the local no and yes */
- static const char *yesValue;
-
- static const char *VersionFormat; /* Version Format String */
- static const int myVersion = 100; /* Version multiplied by 100 */
- BOOL InMsgPrint = NO;
-
- /* Factory (Class) Methods */
-
- + initialize
- /* Class variable initialization. DO NOT call from subclasses. */
- {
- if (self == [MultApp class]) {
- [self setVersion:myVersion];
- [self setDocClass:[MultDoc class]];
- VersionFormat = NXCopyStringBufferFromZone(LocalString("Version %.2f"), MyZone);
- theAppName = NXCopyStringBufferFromZone([NXApp appName],MyZone);
- noValue = NXCopyStringBufferFromZone(LocalString("NO"),MyZone);
- yesValue = NXCopyStringBufferFromZone(LocalString("YES"),MyZone);
- }
- return self;
- }
-
- + setDocClass:newDoc
- /* Sets the document class and the file extensions to be used. Requires */
- /* the document class to implement a class method to return the extension */
- /* and the file types. */
- {
- docClass = newDoc;
- return self;
- }
-
- + docClass
- {
- return docClass;
- }
-
- /* Private C functions used to implement methods in this class. */
-
- static void initMenu(id menu)
- /*
- * Sets the updateAction for every menu item which sends to the
- * First Responder (i.e. their target is nil). When autoupdate is on,
- * every event will be followed by an update of each of the menu items
- * which is visible. This keep all unavailable menu items dimmed out
- * so that the user knows what options are available at any given time.
- */
- {
- int count;
- id matrix, cell;
- id matrixTarget, cellTarget;
-
- matrix = [menu itemList];
- matrixTarget = [matrix target];
-
- count = [matrix cellCount];
- while (count--) {
- cell = [matrix cellAt:count :0];
- cellTarget = [cell target];
- if (!matrixTarget && !cellTarget) {
- [cell setUpdateAction:@selector(menuItemUpdate:) forMenu:menu];
- } else if ([cell hasSubmenu]) {
- initMenu(cellTarget);
- } else if (cellTarget == [NXApp delegate])
- [cell setUpdateAction:@selector(menuItemUpdate:) forMenu:menu];
- }
- }
-
- static id documentInWindow(id window)
- /*
- * Checks to see if the passed window's delegate is a document.
- * If it is, it returns that document, otherwise it returns nil.
- */
- {
- id document = [window delegate];
- if (document) return [document isKindOf:docClass] ? document : nil;
- else return nil;
- }
-
- static id findDocument(const char *name)
- /*
- * Searches the window list looking for a document with the specified name.
- * Returns the window containing the document if found.
- * If name == NULL then the first document found is returned.
- */
- {
- int count;
- id document, window, windowList;
-
- windowList = [NXApp windowList];
- count = [windowList count];
- while (count--) {
- window = [windowList objectAt:count];
- document = documentInWindow(window);
- if (document && (!name || !strcmp([document fileName], name))) return window;
- }
-
- return nil;
- }
-
- static id openFile(const char *directory, const char *name, BOOL display)
- /*
- * Opens a file with the given name in the specified directory.
- * If we already have that file open, it is ordered front.
- * Returns the document if successful, nil otherwise.
- */
- {
- id window;
- char buffer[MAXPATHLEN+1], path[MAXPATHLEN+1];
-
- if (name && *name) {
- if (!directory) directory = ".";
- else if (*directory != '/') {
- strcpy(buffer, "./");
- strcat(buffer, directory);
- directory = buffer;
- }
- if (!chdir(directory) && getwd(path)) {
- strcat(path, "/");
- strcat(path, name);
- window = findDocument(path);
- if (window) {
- if (display) [window makeKeyAndOrderFront:window];
- return [window delegate];
- } else return [docClass newFromFile:path];
- } else Notify(LocalString("Open: path invalid"), directory);
- }
-
- return nil;
- }
-
-
- /* Public Methods */
-
- - currentDocument
- {
- return documentInWindow([NXApp mainWindow]);
- }
-
- - (const char *)currentDirectory
- /* Returns the current document's directory */
- {
- const char *retval = [[self currentDocument] directory];
- if (!retval || !*retval) retval = defaultDir;
- return retval;
- }
-
- - setDefaultDir:(const char *)dir
- {
- sprintf(defaultDir,"%s",dir);
- return self;
- }
-
- - (const char *)launchDirectory
- {
- return launchDir;
- }
-
-
- /* Default support methods */
- // These functions manage the app's behavior when it quits with unsaved documents
-
- - (BOOL)saveAll
- {
- return saveAll;
- }
-
- - setSaveAll:(BOOL)value
- {
- saveAll = value;
- return self;
- }
-
- - (BOOL)dumpAll
- {
- return dumpAll;
- }
-
- - setDumpAll:(BOOL)value
- {
- dumpAll = value;
- return self;
- }
-
-
- /* Shared Panels */
-
- - info:sender
- /*
- * Returns the information Panel if it hasn't already been loaded.
- */
- {
- id versionField; /* version field in info panel */
- char buf[20];
- if (!infoPanel) {
- NXZone *zone = NXCreateChildZone(MyZone, vm_page_size, vm_page_size, YES);
- NXNameZone(zone,"infoPanel");
- LoadLocalNib(LocalString("Info.nib"),self,YES,zone);
- versionField = NXGetNamedObject("VersionNumber", infoPanel);
- if (versionField) {
- sprintf(buf, VersionFormat,theVersion);
- [versionField setStringValue:buf];
- }
- NXMergeZone(zone);
- }
- [infoPanel orderFront:self];
- return infoPanel;
- }
-
- - pref:sender
- /*
- * The preferences panel is a separate nib module and only loaded on demand.
- * When loaded, the object that manages the panel is asked to update it.
- */
- {
- if (!prefPanel) {
- NXZone *zone = NXCreateChildZone(MyZone, vm_page_size, vm_page_size, YES);
- LoadLocalNib(LocalString("Pref.nib"),self,NO,zone);
- NXMergeZone(zone);
- }
- [[prefPanel delegate] load:self];
- [prefPanel orderFront:self];
- return prefPanel;
- }
-
- - saveAsPanel:sender
- {
- id savepanel = [SavePanel new];
- [savepanel setAccessoryView:nil];
- [savepanel setRequiredFileType:DocExtension];
- return savepanel;
- }
-
- - pageLayout:sender
- /*
- * Returns the application-wide PageLayout panel, with margins.
- */
- {
- return pageMargin;
- }
-
- - stringSet:sender
- /*
- * Returns the application-wide string table, if it exists.
- */
- {
- if (stringSet) return stringSet;
- else return nil;
- }
-
- - help:sender
- {
- if (!helpPanel) {
- NXZone *zone = NXCreateChildZone(MyZone, vm_page_size, vm_page_size, YES);
- LoadLocalNib(LocalString("Help.nib"),self,NO,zone);
- NXMergeZone(zone);
- }
- [[helpPanel delegate] generalHelp:self];
- [helpPanel orderFront:self];
- return helpPanel;
- }
-
-
- /* Target/Action Methods */
-
- - new:sender
- /*
- * Called by pressing New in the Document menu.
- */
- {
- [[docClass class] new];
- return self;
- }
-
- - open:sender
- /*
- * Called by pressing Open... in the Document menu.
- */
- {
- const char *directory;
- const char *const *files;
- const char *const myType[2] = {DocExtension, NULL};
- id openpanel = [[OpenPanel new] allowMultipleFiles:YES];
-
- directory = [self currentDirectory];
- if (directory && (*directory == '/')) [openpanel setDirectory:directory];
- if ([openpanel runModalForTypes:myType]) {
- files = [openpanel filenames];
- directory = [openpanel directory];
- while (files && *files) {
- haveOpenedDocument = openFile(directory, *files, YES) || haveOpenedDocument;
- files++;
- }
- }
-
- return self;
- }
-
- - saveAll:sender
- /*
- * Saves all the documents.
- */
- {
- int count;
- id windowList;
-
- windowList = [NXApp windowList];
- count = [windowList count];
- while (count--) {
- [documentInWindow([windowList objectAt:count]) save:self];
- }
-
- return self;
- }
-
- - print:sender
- {
- return [[[self currentDocument] view] printPSCode:sender];
- }
-
- - mailToMe:sender
- // Stolen from Opener 3.0. Thanks, Michael!
- {
- char subj[256], w[256] = "whoami";
- char body[4096]="\
- Subrata:\n\n\
- Great source code! It runs like beauty in the night...\n\
- BUT! I do have a few comments:\n\n\
- <insert accolades, criticisms & suggestions here>\n\n\
- Sincerely,\n\
- ";
- #define call(a,b) [s performRemoteMethod:a with:b length:strlen(b)+1]
- id s = [NXApp appSpeaker];
- port_t mailPort = NXPortFromName("Mail", NULL); // make sure app is launched
-
- mailPort = NXPortFromName("MailSendDemo",NULL);
- if (mailPort == PORT_NULL) {
- Notify(LocalString("Suggestion attempt failed with Missing Port to Mail"),LocalString("Check if Mail is running."));
- return self;
- }
- [s setSendPort:mailPort];
-
- sprintf(subj,"Comments and suggestions for ``%s'', Version %.2f ",theAppName,theVersion);
- strcat(body,execstr(w)); strcat(body,"\n");
- call("setTo:","ssircar@canon.com");
- call("setSubject:",subj);
- call("setBody:",body);
-
- return self;
- }
-
-
- /* Automatic update methods */
-
- - (BOOL)menuItemUpdate:menuCell
- /*
- * Method called by all menu items which send their actions to the
- * First Responder. First, if the object which would respond if the
- * action was sent down the responder chain also responds to the message
- * validateCommand:, then it is sent validateCommand: to determine
- * whether that command is valid now; otherwise, if there is a responder
- * to the message, then it is assumed that the item is valid.
- * The method returns YES if the cell has changed its appearance (so that
- * the caller (a Menu) knows to redraw it).
- * This method also traps menu items sending to this class, and sets the
- * action the same way.
- */
- {
- SEL action;
- id responder, target;
- BOOL enable;
-
- target = [menuCell target];
- enable = [menuCell isEnabled];
-
- if (!target) {
- action = [menuCell action];
- responder = [NXApp calcTargetForAction:action];
- if ([responder respondsTo:@selector(validateCommand:)]) {
- enable = [responder validateCommand:menuCell];
- } else enable = responder ? YES : NO;
- } else if (target == self) enable = [self validateCommand:menuCell];
-
- if ([menuCell isEnabled] != enable) {
- [menuCell setEnabled:enable];
- return YES;
- } else return NO;
- }
-
- - (BOOL)validateCommand:menuCell
- /* The only messages the delegate is asked to validate are SaveAll and Print. */
- {
- SEL action = [menuCell action];
-
- if ((action == @selector(saveAll:)) || (action == @selector(print:))) return findDocument(NULL) ? YES : NO;
-
- return YES;
- }
-
- - setupPageLayout:(float)lm :(float)rm :(float)tm :(float)bm
- {
- if (!pageMargin) {
- pageMargin = [PageMargin new];
- [pageMargin setPlpAccessory:plpAccessory];
- }
- [pageMargin setValues:lm right:rm top:tm bottom:bm];
- [pageMargin writePrintInfo];
- return self;
- }
-
- /* Application Delegate Methods */
-
- - appWillInit:sender
- {
- char temp[MAXPATHLEN+1];
- float lm,rm,tm,bm;
-
- #ifndef DEBUG /* Don't Dump Core if not Debugging */
- struct rlimit rl={ 0, 0};
- getrlimit( RLIMIT_CORE, &rl);
- rl.rlim_cur=0;
- setrlimit( RLIMIT_CORE, &rl);
- #endif
-
- /* Check and load the application defaults. The basics are the quit */
- /* behavior and the page margins. Also sets the menu updating flag. */
-
- if (!NXGetDefaultValue(theAppName,LocalString("SaveAll"))) sprintf(temp,noValue);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("SaveAll")));
- if (!strcmp(temp,yesValue)) saveAll = YES;
- if (!NXGetDefaultValue(theAppName,LocalString("DumpAll"))) sprintf(temp,noValue);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("DumpAll")));
- if (!strcmp(temp,yesValue)) dumpAll = YES;
-
- if (!NXGetDefaultValue(theAppName,LocalString("LeftMargin"))) sprintf(temp,marginDefault);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("LeftMargin")));
- sscanf(temp,"%f",&lm);
- if (!NXGetDefaultValue(theAppName,LocalString("RightMargin"))) sprintf(temp,marginDefault);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("RightMargin")));
- sscanf(temp,"%f",&rm);
- if (!NXGetDefaultValue(theAppName,LocalString("TopMargin"))) sprintf(temp,marginDefault);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("TopMargin")));
- sscanf(temp,"%f",&tm);
- if (!NXGetDefaultValue(theAppName,LocalString("BottomMargin"))) sprintf(temp,marginDefault);
- else sprintf(temp,NXGetDefaultValue(theAppName,LocalString("BottomMargin")));
- sscanf(temp,"%f",&bm);
-
- [self setupPageLayout:lm :rm :tm :bm];
-
- [NXApp setAutoupdate:YES];
-
- return self;
- }
-
- - appDidInit:sender
- /*
- * Register our window with the Workspace for icon dropping.
- * Check for files to open specified on the command line.
- * Initialize the menus and check if we were opened to print or quit.
- * If there are no open documents, then open blank documents.
- */
- {
- int i;
- char buffer[MAXPATHLEN+1], temp[MAXPATHLEN+1];
- char *directory, *name, *ext;
- u_int windowNum;
- id speaker;
-
- /* register our app icon window with the workspace */
- NXConvertWinNumToGlobal([[NXApp appIcon] windowNum], &windowNum);
- speaker = [NXApp appSpeaker];
- [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
- [speaker registerWindow:windowNum
- toPort:[[NXApp appListener] listenPort]];
-
- getAppDirectory(launchDir);
- [self setDefaultDir:NXHomeDirectory()];
-
- /* Check for command line files to open */
- if (NXArgc > 1) {
- for (i = 1; i < NXArgc; i++) {
- strcpy(buffer, NXArgv[i]);
- ext = rindex(buffer, '.');
- if (!ext || strcmp(++ext, DocExtension)) {
- strcat(buffer,".");
- strcat(buffer, DocExtension);
- }
- if (*buffer == '/') {
- directory = "/";
- name = buffer;
- name++;
- } else {
- name = rindex(buffer, '/');
- if (name) {
- *name++ = '\0';
- sprintf(temp,"%s/%s",launchDir,buffer);
- directory = temp;
- } else {
- name = buffer;
- directory = NULL;
- }
- }
- haveOpenedDocument = openFile(directory, name, YES) || haveOpenedDocument;
- }
- }
-
- if (!haveOpenedDocument) [self new:self]; /* if none opened, open one */
- if (NXGetDefaultValue(theAppName,LocalString("Quit"))) {
- [NXApp activateSelf:YES];
- NXPing();
- [NXApp terminate:self];
- }
-
- initMenu([NXApp mainMenu]);
-
- return self;
- }
-
- - appWillTerminate:sender
- /*
- * Overridden to be sure all documents get an opportunity to be saved
- * before exiting the program. Save the defaults too.
- */
- {
- int count, choice;
- float lm,rm,tm,bm;
- char temp[100];
- id window, document, windowList;
-
- windowList = [NXApp windowList];
- count = [windowList count];
- [pageMargin getValues:&lm right:&rm top:&tm bottom:&bm];
- sprintf(temp,"%f",lm);
- NXWriteDefault([NXApp appName],LocalString("LeftMargin"),temp);
- sprintf(temp,"%f",rm);
- NXWriteDefault([NXApp appName],LocalString("RightMargin"),temp);
- sprintf(temp,"%f",tm);
- NXWriteDefault([NXApp appName],LocalString("TopMargin"),temp);
- sprintf(temp,"%f",bm);
- NXWriteDefault([NXApp appName],LocalString("BottomMargin"),temp);
- if (saveAll) {
- while (count--) {
- document = [[windowList objectAt:count] delegate];
- if ([document respondsTo:@selector(needsSaving)] && [document needsSaving]) {
- [document save:self];
- }
- }
- NXWriteDefault(theAppName,LocalString("SaveAll"),yesValue);
- NXWriteDefault(theAppName,LocalString("DumpAll"),noValue);
- } else if (dumpAll) {
- NXWriteDefault(theAppName,LocalString("DumpAll"),yesValue);
- NXWriteDefault(theAppName,LocalString("SaveAll"),noValue);
- } else {
- NXWriteDefault(theAppName,LocalString("DumpAll"),noValue);
- NXWriteDefault(theAppName,LocalString("SaveAll"),noValue);
- while (count--) {
- window = [windowList objectAt:count];
- document = [window delegate];
- if ([document respondsTo:@selector(needsSaving)] && [document needsSaving]) {
- choice = NXRunAlertPanel(LocalString("Quit"),
- LocalString("You have unsaved documents."),
- LocalString("Review Unsaved"),
- LocalString("Quit Anyway"),
- LocalString("Cancel"));
- if (choice == NX_ALERTOTHER) return nil;
- else if (choice == NX_ALERTALTERNATE) return self;
- else if (choice == NX_ALERTDEFAULT) {
- count = 0;
- choice = [windowList count];
- while (choice--) {
- window = [windowList objectAt:choice];
- document = [window delegate];
- if ([document respondsTo:@selector(windowWillClose:)]) {
- if ([document windowWillClose:self]) [window close];
- else return nil;
- }
- }
- }
- }
- }
- }
-
- return self;
- }
-
- - (int)appOpenFile:(const char *)path type:(const char *)type
- /*
- * This method is performed whenever a user double-clicks on an icon
- * in the Workspace Manager representing a app program document.
- */
- {
- char *name;
- char directory[MAXPATHLEN+1];
-
- if (type && !strcmp(type, DocExtension)) {
- strcpy(directory, path);
- name = rindex(directory, '/');
- if (name) {
- #ifdef DEBUG
- printf("Directory %s: File %s\n",directory,name);
- #endif
- if (name != index(directory, '/')) {
- *name++ = '\0';
- if (openFile(directory, name, YES)) {
- haveOpenedDocument = YES;
- return YES;
- }
- } else {
- name++;
- if (openFile("/", name, YES)) {
- haveOpenedDocument = YES;
- return YES;
- }
- }
- #ifdef DEBUG
- printf("After Open, File is %s\n",name);
- #endif
- }
- }
-
- return NO;
- }
-
- - (BOOL)appAcceptsAnotherFile:sender
- /*
- * We accept any number of appOpenFile:type: messages.
- */
- {
- return YES;
- }
-
- - (int)app:sender unmounting:(const char *)fullPath
- {
- id windowList = [NXApp windowList];
- int count = [windowList count];
- id document = NULL;
-
- /* if any of our documents are in that path, close them and notify the user */
-
- while (count--) {
- document = documentInWindow([windowList objectAt:count]);
- if (document && (!strncmp([document directory],fullPath,strlen(fullPath)))) {
- Notify(fullPath,LocalString("is being unmounted; documents here will close."));
- /* Use performClose so that the window delegate will be notified. */
- [[document window] performClose:self];
- }
-
- }
- /* the current directory is wherever our current document is, so we're all set */
- return 0;
- }
-
-
- /* Listener/Speaker remote methods */
-
- // IconDragging Stuff, oh boy, oh boy!
- static char **filePath = NULL;
- static int files = 0;
-
- - (int)iconEntered:(int)windowNum at:(double)x :(double)y
- iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
- iconWidth:(double)iconWidth iconHeight:(double)iconHeight
- pathList:(char *)pathList
- {
- char *stringPos, *tempPtr;
- char tempBuf[MAXPATHLEN+1];
- int count = 0;
-
- if (filePath) {
- freeList(filePath);
- filePath = NULL;
- }
- stringPos = tempPtr = pathList;
- files = 0;
-
- /* This code just parses the pathList for the filenames and explictly */
- /* null-terminates them after copying into a buffer. It appends that */
- /* buffer to the dynamically-allocated filelist which keeps track of it */
-
- /* the number of tabs + 1 equals the number of files dragged in */
-
- while (stringPos = index(stringPos, '\t')) {
- count = (int)(stringPos-tempPtr);
- strncpy(tempBuf,tempPtr,count);
- *(tempBuf+count) = '\0';
- filePath = addFile(tempBuf,filePath,files,MyZone);
- files++;
- stringPos++;
- tempPtr=stringPos;
- }
- strncpy(tempBuf,tempPtr,strlen(tempPtr));
- *(tempBuf+strlen(tempPtr)) = '\0';
- filePath = addFile(tempBuf,filePath,files,MyZone);
- files++;
-
- return 0;
- }
-
- - (int)iconExitedAt:(double)x :(double)y
- // Throw away the files that were just waved in our faces
- {
- freeList(filePath);
- filePath = NULL;
- files = 0;
- return 0;
- }
-
- - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
- // try to open the files in FileList
- {
- char *strPtr;
-
- /* accept the icon */
- *flag = 1;
-
- NX_DURING
- while (files--) {
- strPtr = rindex(filePath[files],'/');
- if (strPtr != index(filePath[files],'/')) {
- *strPtr++ = '\0';
- openFile(filePath[files],strPtr,YES);
- } else {
- strPtr++;
- openFile("/",strPtr,YES);
- }
- }
- NX_HANDLER
- NX_ENDHANDLER
-
- return 0;
- }
-
- // Filename and path methods
- - (int)msgDirectory:(const char **)fullPath ok:(int *)flag
- {
- *fullPath = [self currentDirectory];
- if (*fullPath) *flag = YES;
- else {
- *fullPath = "";
- *flag = NO;
- }
- return 0;
- }
-
- - (int)msgFile:(const char **)fullPath ok:(int *)flag
- {
- const char *file;
-
- file = [[self currentDocument] fileName];
- if (file) {
- *fullPath = file;
- *flag = YES;
- } else {
- *fullPath = "";
- *flag = NO;
- }
-
- return 0;
- }
-
- // Miscellaneous messages we might want to handle
- - (int)msgPrint:(const char *)fullPath ok:(int *)flag
- {
- BOOL close;
- id document = nil;
- char *directory, *name;
- char path[MAXPATHLEN+1];
- char buffer[MAXPATHLEN+1];
-
- InMsgPrint = YES;
- strcpy(buffer, fullPath);
- name = rindex(buffer, '/');
- if (name) {
- *name++ = '\0';
- directory = buffer;
- } else {
- name = buffer;
- directory = NULL;
- }
- if (!chdir(directory) && getwd(path)) {
- strcat(path, "/");
- strcat(path, name);
- document = [findDocument(path) delegate];
- }
- if (document) close = NO;
- else {
- document = openFile(directory, name, NO);
- if (document) haveOpenedDocument = YES;
- close = YES;
- }
- if (document && ![[document view] isEmpty]) {
- [NXApp setPrintInfo:[document printInfo]];
- [[document view] printPSCode:self];
- if (close) [[[document view] window] close];
- *flag = YES;
- } else *flag = NO;
- InMsgPrint = NO;
-
- return 0;
- }
-
- - (int)msgVersion:(const char **)aString ok:(int *)flag
- {
- char buf[20];
-
- sprintf(buf, VersionFormat, theVersion);
- *aString = NXCopyStringBuffer(buf);
- *flag = YES;
-
- return 0;
- }
-
- - (int)msgQuit:(int *)flag
- {
- *flag = ([NXApp terminate:self] ? NO : YES);
- return 0;
- }
-
- @end
-
-